Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");



var examined = [];
var listaItem = [];
var unlistaItem = [];
var unblocked = [];
var blocked = [];


let policy =
{
  classDescription: "AWC2 content policy",
  classID: Components.ID("{12345678-1234-1234-1234-123456789abc}"),
  contractID: "@awc2.net/test-policy;1",
  xpcom_categories: ["content-policy"],
  

  init: function()
  {
    let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
    registrar.registerFactory(this.classID, this.classDescription, this.contractID, this);

    let catMan = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
    for each (let category in this.xpcom_categories)
      catMan.addCategoryEntry(category, this.contractID, this.contractID, false, true);

    onShutdown.add((function()
    {
      for each (let category in this.xpcom_categories)
        catMan.deleteCategoryEntry(category, this.contractID, false);

      // This needs to run asynchronously, see bug 753687
      Services.tm.currentThread.dispatch(function()
      {
        registrar.unregisterFactory(this.classID, this);
      }.bind(this), Ci.nsIEventTarget.DISPATCH_NORMAL);
    }).bind(this));
    
  },

  // nsIContentPolicy interface implementation
  shouldLoad: function(contentType, contentLocation, requestOrigin, node, mimeTypeGuess, extra)
  {
    /*dump("shouldLoad: " + contentType + " " +
                          (contentLocation ? contentLocation.spec : "null") + " " +
                          (requestOrigin ? requestOrigin.spec : "null") + " " +
                          node + " " +
                          mimeTypeGuess + "\n");*/
                          
    
    var regex = new RegExp(/^http|https|ftp/gmi);
        
    var match = regex.exec(contentLocation.spec);
    
    if(!match) {
        return Ci.nsIContentPolicy.ACCEPT;
    }
    
    url = contentLocation.spec;
    
    //var blocked = storage.getItem("blacklist");
    //blocked = (blocked ? blocked.split(",") : []);
    
    //var unblocked = storage.getItem("unblocked");
    //unblocked = (unblocked ? unblocked.split(",") : []);
    
    if(unblocked.lenght != 0) {
        for( id in unblocked) {
            if(url.indexOf(unblocked[id]) != -1) {
                //dump("SBlocco url: "+url);
                
                return Ci.nsIContentPolicy.ACCEPT;
            }
        }
    }
    
    // if this url is in blocked array stop it
    if(blocked.lenght != 0) {
        for( id in blocked) {
            if(url.indexOf(blocked[id]) != -1) {
                //dump("Blocco url: "+url);
                
                addBlockedItem(blocked[id]);
                rrTBB.setAttribute("disabled", "false");
                
                return Ci.nsIContentPolicy.REJECT;
            }
        }
    }
    else rrTBB.setAttribute("disabled", "true");
    
    examined.push(url);
    ws.startCheck(url);
    
    
    return Ci.nsIContentPolicy.ACCEPT;
  },

  shouldProcess: function(contentType, contentLocation, requestOrigin, node, mimeTypeGuess, extra)
  {
    dump("shouldProcess: " + contentType + " " +
                            (contentLocation ? contentLocation.spec : "null") + " " +
                            (requestOrigin ? requestOrigin.spec : "null") + " " +
                            node + " " +
                            mimeTypeGuess + "\n");
    return Ci.nsIContentPolicy.ACCEPT;
  },

  // nsIFactory interface implementation
  createInstance: function(outer, iid)
  {
    if (outer)
      throw Cr.NS_ERROR_NO_AGGREGATION;
    return this.QueryInterface(iid);
  },

  // nsISupports interface implementation
  QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy, Ci.nsIFactory])
};

policy.init();


var ws = {
    getDomain: function (url) {
        
        var regex1 = new RegExp(/[^:]*(:\/\/)?([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})(:[0-9]+)?\/?.*/gmi);
        var match = regex1.exec(url);
        
        if(match) {
            
            console.log("Dominio: "+match);
            return "://"+match[2]+"/";
        }
        
        var regex = new RegExp(/[^:]*(:\/\/)?([^.]*[\.]?[^.]+[\.][^\/]+).*/gmi);
        
        match = regex.exec(url);
        
        if(match) {
            
            //console.log("Dominio: "+match[2]);
            return "://"+match[2]+"/";
        }
    },
    getPage: function (url, callback) {
        
        var xhr = new createXMLHttpRequest();

        xhr.open('GET', url, true);
    
        xhr.onerror = function() {
            document.documentElement.innerHTML = 'Error getting Page';
        }
        
        
        
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4) {
                if (xhr.status != 200)    
                    response = xhr.status;
                else
                    response = xhr.responseText;

                callback(response);
                
            }
        }
        xhr.send(null);

    },
    
    
    checkScript: function (response) {
        var blackList = [];
        var domain;
        var regex = new RegExp(/<!-- Reliability: ([0-9]\.[0-9]) --><script[^>]*src[^>]*=[^>]*[\"']([^>\"']*)[\"'][^>]*>[^>]*\/script[^>]*><!-- end -->/gmi);
        var match = regex.exec(response);
        
        while(match != null) {
            domain = ws.getDomain(match[2]);
            blackList.push(domain);
            
            match = regex.exec(response);
        }
        updateBlacklist(blackList);

    },
    checkIframe: function (response) {
        var blackList = [];
        var regex = new RegExp(/<!-- Reliability: ([0-9]\.[0-9]) --><iframe[^>]*src[^>]*=[^>]*[\"']([^>\"']*)[\"'][^>]*>[^>]*\/iframe[^>]*><!-- end -->/gmi);
        var match = regex.exec(response);
        
        while(match != null) {
            
            domain = ws.getDomain(match[2]);
            blackList.push(domain);
            
            match = regex.exec(response);
        }
        updateBlacklist(blackList);
    },
    checkApplet: function (response) {
        var blackList = [];
        var regex = new RegExp(/<!-- Reliability: ([0-9]\.[0-9]) --><applet[^>]*codebase=[^>"']*["']([^>"']+)["'][^>]*>.*\/applet[^>]*><!-- end -->/gmi);
        var match = regex.exec(response);
        while(match != null) {
            
            domain = ws.getDomain(match[2]);
            blackList.push(domain);
            
            match = regex.exec(response);
        }
        updateBlacklist(blackList);
    },
    checkObject: function (response) {
        var blackList = [];
        var regex = new RegExp(/<!-- Reliability: ([0-9]\.[0-9]) --><object[^>]*data[^>]*=[^>]*["']([^>"']*)["'][^>]*>.*\/object[^>]*><!-- end -->/gmi);
        var match = regex.exec(response);
        while(match != null) {
            
            domain = ws.getDomain(match[2]);
            blackList.push(domain);
            
            match = regex.exec(response);
        }
        updateBlacklist(blackList);
    },
    checkImg: function (response) {
        var blackList = [];
        var regex = new RegExp(/<!-- Reliability: ([0-9]\.[0-9]) --><img[^>]*src[^>="']*=[^>"']*["']([^>"']+)["'][^>]*><!-- end -->/gmi);
        var match = regex.exec(response);
        while(match != null) {
            domain = ws.getDomain(match[2]);
            blackList.push(domain);
            
            match = regex.exec(response);
        }
        updateBlacklist(blackList);
    },
    
    startCheck: function (url) {
        this.getPage(url, function(response) {
            
            ws.checkScript(response);
            ws.checkIframe(response);
            ws.checkApplet(response);
            ws.checkImg(response);
            ws.checkObject(response);
        });
    }
}

function createXMLHttpRequest() {
    return Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
       .createInstance(Components.interfaces.nsIXMLHttpRequest);    
}

function updateBlacklist(newList) {
    var tmp = blocked;
    tmp = (tmp ? tmp.split(",") : []);
    
    for( id in newList ) {
        if(!in_array(newList[id], tmp)) {
            tmp.push(newList[id]);
        }
    }
    blocked = tmp;
}

function in_array(needle, haystack) {
    var length = haystack.length;
    for(var i = 0; i < length; i++) {
        if(haystack[i] == needle) {
            return true;
        }
    }
    return false;
}

function addUnblockedItem(url) {
    if(in_array(url,unlistaItem)) return;
    
    // delete from menuitem
    if(in_array(url,listaItem)) {
        var item = documento.getElementById(url);
        item.setAttribute("label", "Blocca "+url);
        item.removeEventListener("command", sbloccaItem);
        item.addEventListener("command", bloccaItem, true);
    }
    
    unlistaItem.push(url);
}

function addBlockedItem(url) {
    if(in_array(url,listaItem)) return;
    
    if(in_array(url, unblocked)) return;
    
    
    listaItem.push(url);
    let menuitem = documento.createElementNS(NS_XUL, "menuitem");
    menuitem.setAttribute("label", "Sblocca "+url);
    menuitem.setAttribute("id", url);
    menuitem.addEventListener("command", sbloccaItem, true);
    itemList.appendChild(menuitem);
}

function sbloccaItem(e) {
    var url = e.currentTarget.getAttribute("id");
    
    if(in_array(url, unblocked)) return;
    unblocked.push(url);
    
    
    var item = documento.getElementById(url);
    item.setAttribute("label", "Blocca "+url);
    item.removeEventListener("command", sbloccaItem, true);
    item.addEventListener("command", bloccaItem, true);
    
    winz.gBrowser.reload();
}

function bloccaItem(e) {
    var url = e.currentTarget.getAttribute("id");
    
    
    var id = unblocked.indexOf(url);
    if(id!=-1) unblocked.splice(id, 1);
    
    var id = unlistaItem.indexOf(url);
    if(id!=-1) unlistaItem.splice(id, 1);
    
    var item = documento.getElementById(url);
    item.setAttribute("label", "Sblocca "+url);
    item.removeEventListener("command", bloccaItem, true);
    item.addEventListener("command", sbloccaItem, true);

    winz.gBrowser.reload();
}
